#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#include "vpi.h"
#include "debug.h"

void vpi_print_pack_helper(const unsigned char *buff, unsigned int len)
{
	int i = 0;
	
	printf("buf len = %d,Packet[HEX]: ",len);
	for(i=0;i<len;i++)
		printf("%02x ", buff[i]);
	printf("\n");
}

void vpi_print_package(const unsigned char *buff, unsigned int len)
{
    int i = 0;
    int ret = 0;

	if(len < 256)// max limit = 256	
	{
		char tmp[1024] = {0};
		for(i = 0; i < len; i++)
			ret += snprintf(tmp+ret, sizeof(tmp)-ret, "%02x ",buff[i]);
		PLOG(DBG, "buf len = %d,Packet[HEX]: %s\n",len, tmp);
	}
	else
	{
		vpi_print_pack_helper(buff,len);
	}
}

/** return int type for extension */
int vpi_calc_checksum(const unsigned char *buff, int len)
{
	int i;
	unsigned int sum = 0;/* ensure each byte to unsigned */
	int checksum = 0;

	if(buff == NULL || len <= 0)
		return 0;

    for(i = 0; i < len; i++)
    {
        sum += buff[i];
    }

	/* one byte checksum to ensure greater than 0 */
	checksum = sum & 0xff;
	
	return checksum;
}

void vpi_init_proto_header(sproto_header *header, const sproto_header *defheader)
{
	if(header == NULL || defheader == NULL)
		return ;

	memcpy(header,defheader,sizeof(sproto_header));
}

int vpi_build_package(sproto_package *pack,unsigned char *sendbuff, int len)
{
	int ret = 0;
	int pack_len = 0;

	if(pack == NULL || sendbuff == NULL || pack->msg.content == NULL || len <= 0)
	{
		PLOG(ERR, "invalid params!\n");
		return VPI_EPARAMS;
	}

	pack_len = len;
	memset(sendbuff,0,len);

	if(pack->header.build != NULL)
	{
		ret = pack->header.build(pack->role,&pack->msg,sendbuff,&pack_len);
	}
	else
	{
		PLOG(ERR,"the protocol type 0x%x is not supported!\n",pack->header.type);
		ret = VPI_EPARAMS;
	}

	if(ret == VPI_SUCCESS)
		ret = pack_len;

	return ret;
}

/**
 * parse protocol package uniform interface
 *
 * parse protocol package from recvbuff
 * @param[in] handle vpi handle returned by vpi_handle_init
 * @param[in] recvbuff the protocol raw package that need to parsed
 * @param[in] len recvbuff raw package length
 * @return VPI_SUCCESS if success,or vpi errorcode(<0).
 */
int vpi_parse_package(sproto_package *pack,unsigned char *recvbuff, int len)
{
	int ret = 0;

	if(pack == NULL || recvbuff == NULL || pack->msg.content == NULL || len <= 0)
	{
		PLOG(ERR, "invalid params!\n");
		return VPI_EPARAMS;
	}

	if(pack->header.parse!= NULL)
	{
		ret = pack->header.parse(pack->role,&pack->msg,recvbuff,len);
	}
	else
	{
		PLOG(ERR,"the protocol type 0x%x is not supported!\n",pack->header.type);
		ret = VPI_EPARAMS;
	}

	return ret;
}

VPI_HANDLE vpi_handle_init(VPI_HRDESC proto, int role)
{
	VPI_HANDLE handle = NULL;
	const sproto_header *proto_header = NULL;
	int msg_length = 0;
	void *pcontent = NULL;

	if((proto == NULL) || (proto->type <= 0))
	{
		PLOG(ERR,"invalid protocol description!\n");
		return NULL;
	}
	if((role < ROLE_DEV) || (role >= ROLE_MAX))
	{
		PLOG(ERR,"invalid role:%d\n",role);
		return NULL;
	}

	handle = (VPI_HANDLE)malloc(sizeof(sproto_package));
	if(handle == NULL)
	{
		PLOG(ERR,"malloc error:%s\n",strerror(errno));
		return handle;
	}

	msg_length = proto->length;
	proto_header = proto;

	if(msg_length > 0)
	{
		pcontent = malloc(msg_length);
		if(pcontent == NULL)
		{
			PLOG(ERR,"malloc error:%s\n",strerror(errno));
			free(handle);
			handle = NULL;
		}
		else
		{
			memset(handle,0,sizeof(sproto_package));
			memset(pcontent,0,msg_length);
			handle->role = role;
			vpi_init_proto_header(&handle->header,proto_header);
			handle->msg.length = msg_length;
			handle->msg.content = pcontent;
		}
	}
	else
	{
		free(handle);
		handle = NULL;
	}

	return handle;
}

void vpi_handle_exit(VPI_HANDLE handle)
{
	if(handle != NULL)
	{
		free(handle->msg.content);
		free(handle);
	}
}

